local skynet = require "skynet"
local netpack = require "skynet.websocketnetpack"
local base = require "base"
local filelog = require "filelog"
local filename = "gatenode.lua"
local httpc = require "http.httpc"
local md5 = require "md5"
local configdao = require "configdao"
local timetool = require "timetool"

require "skynet.manager"

require "pubenum"

local Gatenode = {
	gate_service = nil,
	service_manager = {},
	protobuf = nil, 
	decode = nil,
	netpack = nil,
	socket = nil,
	tcpmng = nil,
	eventpool = {},
}

--是否已设置dns服务
local is_set_dns = false

function Gatenode:process(session, source, calltype, msgname, ...)
	if msgname == nil then
		filelog.sys_error(filename.." line22 gatenode:process invalid msgname")
		return
	end
	-- filelog.sys_protomsg(filename.." line25_" .. skynet.self().."__"..calltype.."_"..msgname.."_request", ...)
	local f = self.eventpool[msgname]
	if f == nil then
		filelog.sys_error(filename.." line28 gatenode:processinvalid msgname:"..msgname, ...)		
		return
	end
	local status, result = skynet.pcall(f.process, session, source, ...)
	if not status then
		filelog.sys_error(filename.." line33 gatenode:process skynet.pcall failed", msgname, result, ...)
	end
end

-- 有错误消息的时候，也有只发送消息头，不发送消息体的时候
function Gatenode:send_resmsgto_client(fd, msgname, msgbody, retcode, retstr)
	self.socket.write(fd, netpack.pack(self.decode.s2cpack(self.protobuf, msgname, retcode, retstr, msgbody)))
end

--  从long_tcp_mng 中根据rid 找到对应的agent， 然后一个个发送消息
function Gatenode:notify(rids, msgname, msgbody, retcode, retstr)
	local agent_session = nil
	for k,v in pairs(rids) do
		agent_session = self.tcpmng.get_agent_session(v) -- 这里得到一个结构 {agent, fd}
		if agent_session then
			skynet.send(agent_session.agent, "lua", "cmd", "notify_client", msgname, msgbody, retcode, retstr)
		end
	end
end

-- 从long_tcp_mng 中根据rid 找到对应的agent， 然后一个个发送消息
-- 这里要求ris_values 是个table， rid就是key，调用agent的 func ， value就是参数
-- 主要有五个函数：game_sub_fuwufei， game_balance_diamond， game_sub_fangka， game_balance_fangka, game_half_diamond
function Gatenode:rids_broadcast_func(func, rid_values, ...)
	local agent_session = nil
	for k,v in pairs(rid_values) do
		-- 如果是从redis里面获得，这里的 k 是字符串
		k = tonumber(k)
		agent_session = self.tcpmng.get_agent_session(k) -- 这里的k 是 rid ，和上面notify函数不同，得到一个结构 {agent, fd}
		if agent_session then
			skynet.send(agent_session.agent, "lua", "cmd", func, v, rid_values, ...)
		else
			-- 用户离线了，也必须扣款，而且这里要记录
			skynet.send(".offlinerole", "lua", func, k, v, rid_values, ...)

            --检测是否触发任务,主要针对离线扣费操作
            --skynet.send(".tasksystem", "lua", "check_is_trigger_task", k, func, v, rid_values, ...)
		end
	end
end

-- 获取所有玩家
function Gatenode:get_all_agents()
	return self.tcpmng.get_all_agents()
end

--  从long_tcp_mng 中根据rid 找到对应的agent，返回这个agent
function Gatenode:get_agent_by_rid(objrid)
	local agent_session = nil
	agent_session = self.tcpmng.get_agent_session(objrid) -- 这里得到一个结构 {agent, fd}
	if agent_session then
        local agent = agent_session.agent
        if agent then
            local status,state = pcall(skynet.call, agent, "lua", "cmd", "get_agentstate")
            if not status or state ~= EGateAgentState.GATE_AGENTSTATE_LOGINED then
                return nil
            end
        end
        
		return agent
	else
		return nil
	end
end

--
--发送http请求
--
function Gatenode:send_http_request(rid, request_url)
    local host,url = string.match(request_url,"://(.+%.%w+)/(.+)")
    local recvheader = { }
    url = "/" .. (url or "") 
    
    filelog.sys_info("---start http request---",rid, host, url)
    if not is_set_dns then
        skynet.pcall(httpc.dns) -- 异步dns服务，只设置一次
        is_set_dns = true
    end
	httpc.timeout = 300	        -- 超时3s
	if host == "api.daili.com" then
		host = EAPI_ADDRESS or "192.168.1.75"
	end
    local isok,status,body = skynet.pcall(httpc.post, host, url, {}, recvheader)
    filelog.sys_info("---end http request---", rid, status, body, host, url)
    if status == 200 and body then
        return body
    elseif not is_ok then
        skynet.pcall(httpc.dns)
		return false
    end

    return 
end

function Gatenode:send_bindagency_request(rid, agencyrid, pkgid)
	local check_agency_url = configdao.get_common_conf("check_agency_url")
    local host,url = string.match(check_agency_url,"(.+%.%w+)/(.+)")
    local recvheader = { }
    local cur_time = timetool.get_time()
    local gate2web_key = configdao.get_cfgsvrs_key("gate2web_key")
    local sign = md5.sumhexa(rid .. cur_time .. gate2web_key)
    url = "/" .. (url or "") .. "rid=" .. rid .. "&sign=" .. sign .. "&strtime=" .. cur_time
     	.. "&parent_id=" .. tostring(agencyrid) .. "&pkgid=" .. tostring(pkgid)
    filelog.sys_info("---start http request---",rid, host, url)
    if not is_set_dns then
        skynet.pcall(httpc.dns) -- 异步dns服务，只设置一次
        is_set_dns = true
    end
    httpc.timeout = 300         -- 超时3s
	if host == "api.daili.com" then
		host = EAPI_ADDRESS or "192.168.1.75"
	end
    local result_data = nil
    local isok,status,body = skynet.pcall(httpc.post, host, url, {}, recvheader)
    filelog.sys_info("---end http request---", rid, status, body, host, url)
    if status == 200 and body then
        return body
    elseif not is_ok then
        return false
    end
end
--
--通知平台服发送验证码
--
function Gatenode:notice_platform_server(rid, phonenum, verifcode)
    local sm_url = configdao.get_common_conf("sm_url") or "verqy.jyhd666.com:4321"
    local host,url = string.match(sm_url,"(.+%.%w+)/(.+)")
    local sm_key = configdao.get_common_conf("sm_key") or ""
    local recvheader = { }
    local cur_time = timetool.get_time()
    local sign = md5.sumhexa(phonenum .. cur_time .. sm_key) .. cur_time
    url = "/" .. (url or "") .. "mobile=" ..  phonenum .. "&code=" .. verifcode .. "&" .. "sign=" .. sign
    
    filelog.sys_info("---start http request---", rid, host, url)
    if not is_set_dns then
        skynet.pcall(httpc.dns) -- 异步dns服务，只设置一次
        is_set_dns = true
    end
	httpc.timeout = 300	        -- 超时3s
	if host == "api.daili.com" then
		host = EAPI_ADDRESS or "192.168.1.75"
	end
    local isok,status,body = skynet.pcall(httpc.post,host, url, {}, recvheader)
    filelog.sys_info("---end http request---", rid, status, body, host, url)
    if not is_ok then
        skynet.pcall(httpc.dns)
    end
end

function Gatenode:start()
	skynet.register_protocol {
		name = "client",
		id = skynet.PTYPE_CLIENT,
	}

	-- 重置protobuf解析器到全局唯一的解析器地址
	debug.getregistry().PROTOBUF_ENV = skynet.call(".pbcservice", "lua", "get_protobuf_env")
	self.protobuf = require "protobuf"
	self.decode = require "protopack"

	self.socket = require("skynet.socket")
	self.gate_service = skynet.newservice("wsgate")
	self.service_manager["wsgate"] = self.gate_service
	self.tcpmng = require("long_tcp_mng")		
	skynet.dispatch("lua", function (session, source, ...)
							Gatenode:process(session, source,"lua", ...)
							 end)
	self:init()
	skynet.register(skynet.getenv("nodename"))
end

function Gatenode:add_eventbyname(name, event)
	self.eventpool[name] = require(event)
	self.eventpool[name].service = Gatenode
end

function  Gatenode:init()
	self:add_eventbyname("cmd", "nodemsg/gatenodecmd")
	self:add_eventbyname("socket", "nodemsg/gatenodesocket")
end

skynet.start(function()
	Gatenode:start()
end)
